/*
 * Copyright 2009 Brook Smith brook.smith@paradise.net.nz.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.javagenerate.generator.script.gen;

import java.util.HashSet;
import java.util.Set;

import org.javagenerate.generator.MethodDefinition;
import org.javagenerate.generator.NamingUtils;
import org.javagenerate.generator.script.BasePatternGenerator;
import org.javagenerate.generator.script.ClassDef;
import org.javagenerate.generator.script.GenBeanDefinition;
import org.javagenerate.generator.script.OptionsDefinition;
import org.javagenerate.generator.script.PatternRef;

public class JDODef extends ClassDef {

	private static final OptionsDefinition PERSISTED = new OptionsDefinition("persisted");
	
	private Set<String> dependacies = new HashSet<String>();
	private String objectTypes = "";
	

	public JDODef(String classname, String patternName) {
		super(classname, patternName);
		setAnnotations("@PersistenceCapable");
		getImports().add("javax.jdo.annotations.PersistenceCapable");
		getImports().add("javax.jdo.annotations.Persistent");
		
		getImports().add("com.google.appengine.api.datastore.Key");
		getImports().add("javax.jdo.annotations.PrimaryKey");
		getImports().add("javax.jdo.annotations.IdGeneratorStrategy");

		// Key key persisted(valueStrategy = IdGeneratorStrategy.IDENTITY), PrimaryKey;
		GenBeanDefinition beanDefinition = new GenBeanDefinition(true, true, "key", "Key");
		beanDefinition.setAnnotation("@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)\n@PrimaryKey");
		super.addBeanDefiniation(beanDefinition);
	}

	/**
	 * Check for the persistable option
	 */
	public void processBeanDefiniation(GenBeanDefinition genBeanDefinition) {
		boolean hasGetter = !genBeanDefinition.getName().equals("id");
		GenBeanDefinition beanDefinition = new GenBeanDefinition(hasGetter, true, genBeanDefinition.getName(), genBeanDefinition.getType());
		// int optionIndex = genBeanDefinition.getOptions().indexOf(PERSISTED);
		if (genBeanDefinition.getOptions() != null) {
			String annotations = null;
			for (OptionsDefinition definition : genBeanDefinition.getOptions()) {
				if (annotations == null) {
					annotations = "";
				}
				if (annotations.length() > 0) {
					annotations += "\n";
				}
				if (definition.getOption().equals("persisted")) {
					annotations += "@Persistent" + definition.getOptionsParms();
				} else {
					annotations += "@" + definition.getFullOption();
				}
			}
			beanDefinition.setAnnotation(annotations);
		}
		super.addBeanDefiniation(beanDefinition);
	}
	
	@Override
	public void preWrite() {
		// TODO Auto-generated method stub
		super.preWrite();
		MethodDefinition methodDefinition = new MethodDefinition("Long", "getId");
		methodDefinition.setContent("return key.getId();");
		addMethod(methodDefinition);
		
		
		BasePatternGenerator generator = PatternRef.getBasePatternGenerator(getPatternName());
		ClassDef interfaceDef = generator.getClass("interface");

		getImplements().add(interfaceDef.getClassName() +  (objectTypes.length() > 0 ? "<" + objectTypes + ">" : ""));
		getImports().add(interfaceDef.getPackageName() + "." + interfaceDef.getClassName());

		for (String dependacy : dependacies) {
			generator = PatternRef.getBasePatternGenerator(dependacy);
			ClassDef classDef = generator.getClass("jdo");
			getImports().add(classDef.getPackageName() +"."+ classDef.getClassName());
		}
	}
	
	@Override
	public void addBeanDefiniation(GenBeanDefinition beanDefinition) {
		if (Character.isLowerCase(beanDefinition.getType().charAt(0))) {
			// denotes that this is a Bean based on this pattern, why else would
			// it be lower case?
			String baseName = NamingUtils.upperFirst(beanDefinition.getType());
			GenBeanDefinition thisDef = new GenBeanDefinition(beanDefinition.getName(), baseName + "JDO", beanDefinition.getOptions());
			
			String appendTs = baseName + "JDO";
			if (objectTypes.length() == 0) {
				objectTypes = appendTs;
			} else {
				if (!objectTypes.contains(appendTs)) {
					objectTypes += ", " + appendTs;
				}
			}
			dependacies.add(beanDefinition.getType());
			// <AddressType extends AddressDef>
			processBeanDefiniation(thisDef);
		} else {
			processBeanDefiniation(beanDefinition);
		}
	}
}
